from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.contrib.auth.views import redirect_to_login
from django.template import loader, RequestContext
from django.utils import simplejson

from discussion.forms import CommentForm
from discussion.models import CommentNode

def comment_on_object(request, model, post_comment_redirect=None,
        object_id=None, slug=None, slug_field=None, template_name=None,
        template_loader=loader, extra_context=None, context_processors=None,
        template_object_name='object', form_class=None):
    """
    Generic commenting view.

    Templates:``<app_label>/<model_name>_comment.html``
    Context:
        object
            The object being commented on.
        form
            A form for entering and validating a new comment.
        reply_to
            The comment being replied to, if applicable.
    """
    if extra_context is None: extra_context = {}
    if form_class is None: form_class = CommentForm
    reply_to = None

    # Look up the object to be commented on
    lookup_kwargs = {}
    if object_id:
        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
    elif slug and slug_field:
        lookup_kwargs['%s__exact' % slug_field] = slug
    else:
        raise AttributeError('Generic comment view must be called with either object_id or slug/slug_field.')
    try:
        obj = model._default_manager.get(**lookup_kwargs)
    except ObjectDoesNotExist:
        raise Http404, 'No %s found for %s.' % (model._meta.app_label, lookup_kwargs)

    if request.method == 'POST':
        form = form_class(request.POST)
        if form.is_valid():
            # Determine redirect location
            if post_comment_redirect is not None:
                next = post_comment_redirect
            elif request.REQUEST.has_key('next'):
                next = request.REQUEST['next']
            elif hasattr(obj, 'get_absolute_url'):
                if callable(getattr(obj, 'get_absolute_url')):
                    next = obj.get_absolute_url()
                else:
                    next = obj.get_absolute_url
            else:
                raise AttributeError('Generic comment view must either be called with post_comment_redirect or the object being voted on must define a get_absolute_url method or property.')

            # Set the object being commented on as the commment spcified by
            # reply_to, if it is a valid comment on the same object.
            if form.cleaned_data['reply_to'] is not None:
                try:
                    reply_to = CommentNode.objects.get(pk=form.cleaned_data['reply_to'])
                    if reply_to.object != obj:
                        raise AttributeError('Generic comment view detected an attempt to reply to a comment from a different object.')
                    obj = reply_to
                except CommentNode.DoesNotExist:
                    raise AttributeError('Generic comment view detected an attempt to reply to a non-existent comment.')

            CommentNode.objects.create(user=request.user,
                                       object=obj,
                                       body=form.cleaned_data['body'])
            return HttpResponseRedirect(next)
    else:
        form = form_class()
        # If a reply_to was specified, validate that the comment exists and is
        # for the correct object.
        if request.GET.has_key('reply_to'):
            try:
                reply_to = CommentNode.objects.select_related().get(pk=request.GET['reply_to'])
                if reply_to.object != obj:
                    raise AttributeError('Generic comment view detected an attempt to reply to a comment from a different object.')
                form.initial['reply_to'] = reply_to.id
            except CommentNode.DoesNotExist:
                raise AttributeError('Generic comment view detected an attempt to reply to a non-existent comment')

    if not template_name:
        template_name = '%s/%s_comment.html' % (model._meta.app_label, model._meta.object_name.lower())
    t = template_loader.get_template(template_name)
    c = RequestContext(request, {
        template_object_name: obj,
        'form': form,
        'reply_to': reply_to,
    }, context_processors)
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    response = HttpResponse(t.render(c))
    return response

def edit_comment():
    raise NotImplementedError

def delete_comment():
    raise NotImplementedError
